<template>
    <el-switch v-model="isY" active-text="开启Y轴反转" />
    <canvas id="ice-4_1" width="640" height="400"></canvas>
</template>

<script setup lang="ts">
import { onMounted, ref, watch } from 'vue'
import {
    createGl,
    createShader,
    createProgram,
} from '@/utils'
import catImg from '@/assets/cat.jpeg'
//   const vertexCode = `
//     attribute vec4 a_Position;
//     attribute vec2 a_TexCoord;
//     varying vec2 v_TexCoord;

//     void main () {
//       gl_Position = a_Position;
//       v_TexCoord = a_TexCoord;
//     }
//   `

//   const fragmentCode = `
//     precision mediump float;
//     varying vec2 v_TexCoord;
//     uniform sampler2D u_Sampler;

//     void main () {
//       gl_FragColor = vec4(0., 0., 1., .9);
//     }
//   `
const isY = ref(false);
watch(isY, () => {
    drawImage()
})
let gl: WebGLRenderingContext, program: WebGLProgram, a_Position, canvas: any, img

const drawImage = () => {
    const img = new Image()
    // 图片地址（注意不允许跨域） 使用图片进行纹理映射
    img.src = catImg;
    img.onload = function (e) {
        // 一系列实现纹理映射的相关代码
        console.log('onload', e)

        // 第一步 创建纹理对象
        const texture = gl.createTexture()
        // 反转图像 因为纹理图像和图像坐标刚好上下相反
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, isY.value)

        // 第二步 激活纹理单元 纹理单元支持 多个
        gl.activeTexture(gl.TEXTURE0)

        // 第三步 绑定要使用的纹理对象个 (使用2d纹理，纹理图片)

        // 绑定纹理对象
        gl.bindTexture(gl.TEXTURE_2D, texture)

        // 配置纹理对象
        
        // 首先我们配置 gl.TEXTURE_MIN_FILTER 纹理缩小时的填充方法：
        // 纹理缩小，使用 gl.LINEAR 计算距离中心像素最近的四个像素的平均值
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        // 接着再配置 gl.TEXTURE_WRAP_* 纹理水平、垂直 填充 ：
        // 填充方式都是 gl.CLAMP_TO_EDGE 边缘切割取值
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

        // 最后 将图像分配纹理对象
        // 本文用的图片是 jpeg 格式，所以格式参数均为 gl.RGB
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, img)

        // 第六步 纹理单元传递给片元着色器

        // 获取 uniform 变量地址
        const u_Sampler = gl.getUniformLocation(program, 'u_Sampler')
        // 将 gl.TEXTURE0（0号纹理单元） 分配给 u_Sampler 变量 
        // uniform1i函数用于更新着色器中的uniform变量
        // 第二个参数对应的是gl.TEXTURE0 第0个纹理
        gl.uniform1i(u_Sampler, 0)
        // 画置
        gl.clear(gl.COLOR_BUFFER_BIT)
        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
    }
}

const initGl = () => {
    // 第一步 创建gl
    gl = createGl('#ice-4_1')
    // 第二步 编写着色器
    const vertexCode = `
        attribute vec4 a_Position;
        attribute vec2 a_TexCoord;
        varying vec2 v_TexCoord;

        void main () {
            gl_Position = a_Position;
             v_TexCoord = a_TexCoord;
        }
    `
    const fragmentCode = `
        precision mediump float;
        varying vec2 v_TexCoord;
        uniform sampler2D u_Sampler;
        void main () {
            // gl_FragColor = vec4(0., 0., 1., .9);
        gl_FragColor = texture2D(u_Sampler, v_TexCoord);
        }
    `
    // 第三步 创建program 定义数据 并 传递数据及 创建缓冲区
    const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexCode)
    const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentCode)
    program = createProgram(gl, vertexShader, fragmentShader)
    const verticesTexCoords = new Float32Array([
        -.5, .5, 0, 1,
        -.5, -.5, 0., 0.,
        .5, .5, 1, 1,
        .5, -.5, 1, 0
    ])
    // 定义数据节点数
    const FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
    // 创建缓冲区
    const buffer = gl.createBuffer();
    // 绑定缓冲区对象
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    // 传递数据
    gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW)
    // 缓冲区得到数据后 操作缓冲区
    const a_Position = gl.getAttribLocation(program, 'a_Position');
    const a_TexCoord = gl.getAttribLocation(program, 'a_TexCoord')
    // 传入顶点数据
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0)
    // 允许缓存
    gl.enableVertexAttribArray(a_Position);
    // 传入色值数据
    gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2)
    // 允许缓存
    gl.enableVertexAttribArray(a_TexCoord);
    // 画布清除颜色
    gl.clearColor(0., 0., 0., .9)
    // 规定以特定方式clear
    gl.clear(gl.COLOR_BUFFER_BIT)
    // 绘制三角形
    // gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
    drawImage()
}

onMounted(() => {
    initGl()
})
</script>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
    name: 'Third4_1'
})
</script>